package org.chainsale.bean;

import java.util.List;

import org.chainsale.common.Utils;


public enum Rank {
	
	JUNIOR(1, 0.15, "实习业务员", 1, 2), 
	LEADER(2, 0.05, "组长", 3, 9), 
	
	DIRECTOR1THGEN(3, 0.1, "一代主任", 10, 64), 
	DIRECTOR2THGEN(4, 0.04, "二代主任", 10, 64),
	FINALGENDIRECTOR(5, 0.0, "最后主任", 10, 64),
	
	MANAGER1THGEN(6, 0.12, "一代经理", 65, 599), 
	MANAGER2THGEN(7, 0.03, "二代经理", 65, 599), 
	MANAGER3THGEN(8, 0.02, "三代经理", 65, 599), 
	FINALGENMANAGER(9, 0.0, "最后经理", 65, 599), 
	
	CHIEFSTEP1(10, 0.10, "一阶老总", 600, 600), 
	FINALCHIEFSTEP1(11, 0.0, "最后一阶老总", 600, 600), 
	
	CHIEFSTEP2(12, 0.015, "二阶老总", 600, 600), 
	FINALCHIEFSTEP2(13, 0.0, "最后二阶老总", 600, 600), 
	
	CHIEFSTEP3(14, 0.01, "三阶老总", 600, 600), 
	FINALCHIEFSTEP3(15, 0.0, "最后三阶老总", 600, 600), 
	
	CHIEFSTEP4(16, 0.005, "四阶老总", 600, 600), 
	FINALCHIEFSTEP4(17, 0.0, "最后四阶老总", 600, 600), 
	
	OUTCHIEF(18, 0.0, "出局老总", 600, 600);

	private int level;
	private double percentage;
	private String name;
	private int requiredMin;
	private int requiredMax;

	private Rank(int level, double percentage, String name, int requiredMin, int requiredMax) {
		this.level = level;
		this.percentage = percentage;
		this.name = name;
		this.requiredMin = requiredMin;
		this.requiredMax = requiredMax;
	}

	public static boolean isDirectorByLevel(int level) {
		return level == 3 || level == 4 || level == 5;
	}
	
	public static boolean isManagerByLevel(int level) {
		return level == 6 || level == 7 || level == 8 || level == 9;
	}
	
	public static boolean isCheifStep1ByLevel(int level) {
		return level == 10 || level == 11;
	}
	
	public static boolean isCheifStep2ByLevel(int level) {
		return level == 12 || level == 13;
	}
	
	public static boolean isCheifStep3ByLevel(int level) {
		return level == 14 || level == 15;
	}
	
	public static boolean isCheifStep4ByLevel(int level) {
		return level == 16 || level == 17;
	}
	
	public static Rank getRankByShare(int share) {
		Rank initRank = null;
		
		if (1 <= share && share <= 2) {
			initRank = JUNIOR;
		} else if (3 <= share && share <= 9) {
			initRank = LEADER;
		} else if (10 <= share && share <= 64) {
			initRank = DIRECTOR1THGEN;
		} else if (65 <= share && share <= 599) {
			initRank = MANAGER1THGEN;
		} else if (share >= 600) {
			initRank = CHIEFSTEP1;
		}
		
		return initRank;
	}
	
	
	public static Rank regenerateRank(Practitioner p) {
		Rank currRank = p.getRank();
		
		switch (currRank) {
			case JUNIOR:
				if (canUpgradeRank(p, LEADER)) currRank = LEADER;
				break;
			case LEADER:
				if (canUpgradeRank(p, DIRECTOR1THGEN)) currRank = DIRECTOR1THGEN;
				break;
			case DIRECTOR1THGEN:
				if (canUpgradeRank(p, MANAGER1THGEN)) {
					currRank = MANAGER1THGEN;
				} else {
					// 若伞下已有一个主任, 则升级为二代主任; 若是伞下已有2个主任, 则升级为最后主任
					int directorNum = getAllDirectorNum(p);
					if (directorNum == 1) currRank = DIRECTOR2THGEN;
					else if (directorNum == 2) currRank = FINALGENDIRECTOR;
				}
				break;
			case DIRECTOR2THGEN:
				if (canUpgradeRank(p, MANAGER1THGEN)) {
					currRank = MANAGER1THGEN;
				} else {
					int directorNum = getAllDirectorNum(p);
					if (directorNum == 2) currRank = FINALGENDIRECTOR;
				}
				break;
			case FINALGENDIRECTOR:
				if (canUpgradeRank(p, MANAGER1THGEN)) currRank = MANAGER1THGEN;
				break;
			case MANAGER1THGEN:
				if (canUpgradeRank(p, CHIEFSTEP1)) {
					currRank = CHIEFSTEP1;
				} else {
					// 若伞下已有一个经理, 则升级为二代经理; 若是伞下已有2个经理, 则升级为三代经理; 若是伞下已有3个经理, 则升级为最后经理
					int managerNum = getAllManagerNum(p);
					if (managerNum == 1) currRank = MANAGER2THGEN;
					else if (managerNum == 2) currRank = MANAGER3THGEN;
					else if (managerNum == 3) currRank = FINALGENMANAGER;
				}
				break;
			case MANAGER2THGEN:
				if (canUpgradeRank(p, CHIEFSTEP1)) {
					currRank = CHIEFSTEP1;
				} else {
					int managerNum = getAllManagerNum(p);
					if (managerNum == 2) currRank = MANAGER3THGEN;
					else if (managerNum == 3) currRank = FINALGENMANAGER;
				}
				break;
			case MANAGER3THGEN:
				if (canUpgradeRank(p, CHIEFSTEP1)) {
					currRank = CHIEFSTEP1;
				} else {
					int managerNum = getAllManagerNum(p);
					if (managerNum == 3) currRank = FINALGENMANAGER;
				}
				break;
			case FINALGENMANAGER:
				if (canUpgradeRank(p, CHIEFSTEP1)) currRank = CHIEFSTEP1;
				break;
			case CHIEFSTEP1:
				if (canUpgradeRank(p, CHIEFSTEP2)) {
					currRank = CHIEFSTEP2;
				} else {
					int step1Num = countCheifStep1(p);
					if (step1Num == 1) currRank = FINALCHIEFSTEP1;
				}
				break;
			case FINALCHIEFSTEP1:
				if (canUpgradeRank(p, CHIEFSTEP2)) currRank = CHIEFSTEP2;
				break;
			case CHIEFSTEP2:
				if (canUpgradeRank(p, CHIEFSTEP3)) {
					currRank = CHIEFSTEP3;
				} else {
					int step2Num = countCheifStep2(p);
					if (step2Num == 1) currRank = FINALCHIEFSTEP2;
				}
				break;
			case FINALCHIEFSTEP2:
				if (canUpgradeRank(p, CHIEFSTEP3)) currRank = CHIEFSTEP3;
				break;
			case CHIEFSTEP3:
				if (canUpgradeRank(p, CHIEFSTEP4)) {
					currRank = CHIEFSTEP4;
				} else {
					int step3Num = countCheifStep3(p);
					if (step3Num == 1) currRank = FINALCHIEFSTEP3;
				}
				break;
			case FINALCHIEFSTEP3:
				if (canUpgradeRank(p, CHIEFSTEP4)) currRank = CHIEFSTEP4;
				break;
			case CHIEFSTEP4:
				if (canUpgradeRank(p, OUTCHIEF)) {
					currRank = OUTCHIEF;
				} else {
					int step4Num = countCheifStep4(p);
					if (step4Num == 1) currRank = FINALCHIEFSTEP4;
				}
				break;
			case FINALCHIEFSTEP4:
				if (canUpgradeRank(p, OUTCHIEF)) currRank = OUTCHIEF;
				break;
			case OUTCHIEF:
				
				break;
			default:
				break;
		}
		
		return currRank;
	}
	
	private static boolean canUpgradeRank(Practitioner p, Rank targetRank) {
		boolean canUpgrade = false;
		if (p.getShare() >= targetRank.getRequiredMin()) {
			
			int currRankLevel = p.getRank().getLevel();
			if (currRankLevel >= DIRECTOR1THGEN.level) {
				boolean allMatched = true;
				
				if (isDirectorByLevel(currRankLevel)) {
					for (Practitioner px : p.getUnderlings()) {
						if (px.getRank().level < DIRECTOR1THGEN.level) {
							allMatched = false;
							break;
						}
					}
				} else if (isManagerByLevel(currRankLevel)) {
					for (Practitioner px : p.getUnderlings()) {
						if (px.getRank().level < MANAGER1THGEN.level) {
							allMatched = false;
							break;
						}
					}
				} else if (isCheifStep1ByLevel(currRankLevel)) {
					for (Practitioner px : p.getUnderlings()) {
						if (px.getRank().level < CHIEFSTEP1.level) {
							allMatched = false;
							break;
						}
					}
				} else if (isCheifStep2ByLevel(currRankLevel)) {
					for (Practitioner px : p.getUnderlings()) {
						if (px.getRank().level < CHIEFSTEP2.level) {
							allMatched = false;
							break;
						}
					}
				} else if (isCheifStep3ByLevel(currRankLevel)) {
					for (Practitioner px : p.getUnderlings()) {
						if (px.getRank().level < CHIEFSTEP3.level) {
							allMatched = false;
							break;
						}
					}
				} else if (isCheifStep4ByLevel(currRankLevel)) {
					for (Practitioner px : p.getUnderlings()) {
						if (px.getRank().level < CHIEFSTEP4.level) {
							allMatched = false;
							break;
						}
					}
				}
				
				
				if (allMatched) canUpgrade = true;
			} else {
				canUpgrade = true;
			}
		}
		
		return canUpgrade;
	}
	
	private static int getAllDirectorNum(Practitioner p) {
		int matchedNum = 0;
		List<Practitioner> ps = Utils.selectUnderlingsByLayer(p);
		for (Practitioner pp : ps) {
			if (isDirectorByLevel(pp.getRank().level)) matchedNum++;
			if (matchedNum >= 2) break;
		}
		
		return matchedNum;
	}
	
	private static int getAllManagerNum(Practitioner p) {
		int matchedNum = 0;
		List<Practitioner> ps = Utils.selectUnderlingsByLayer(p);
		for (Practitioner pp : ps) {
			if (isManagerByLevel(pp.getRank().level)) matchedNum++;
			if (matchedNum >= 3) break;
		}
		
		return matchedNum;
	}
	
	private static int countCheifStep1(Practitioner p) {
		int matchedNum = 0;
		List<Practitioner> ps = Utils.selectUnderlingsByLayer(p);
		for (Practitioner pp : ps) {
			if (isCheifStep1ByLevel(pp.getRank().level)) matchedNum++;
			if (matchedNum >= 1) break;
		}
		
		return matchedNum;
	}
	
	private static int countCheifStep2(Practitioner p) {
		int matchedNum = 0;
		List<Practitioner> ps = Utils.selectUnderlingsByLayer(p);
		for (Practitioner pp : ps) {
			if (isCheifStep2ByLevel(pp.getRank().level)) matchedNum++;
			if (matchedNum >= 1) break;
		}
		
		return matchedNum;
	}
	
	private static int countCheifStep3(Practitioner p) {
		int matchedNum = 0;
		List<Practitioner> ps = Utils.selectUnderlingsByLayer(p);
		for (Practitioner pp : ps) {
			if (isCheifStep3ByLevel(pp.getRank().level)) matchedNum++;
			if (matchedNum >= 1) break;
		}
		
		return matchedNum;
	}
	
	private static int countCheifStep4(Practitioner p) {
		int matchedNum = 0;
		List<Practitioner> ps = Utils.selectUnderlingsByLayer(p);
		for (Practitioner pp : ps) {
			if (isCheifStep4ByLevel(pp.getRank().level)) matchedNum++;
			if (matchedNum >= 1) break;
		}
		
		return matchedNum;
	}
	
	
	// getters, setters
	public int getLevel() {
		return level;
	}

	public void setLevel(int level) {
		this.level = level;
	}
//
//	public int getSecondLevel() {
//		return secondLevel;
//	}
//
//	public void setSecondLevel(int secondLevel) {
//		this.secondLevel = secondLevel;
//	}

	public double getPercentage() {
		return percentage;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getRequiredMin() {
		return requiredMin;
	}

	public void setRequiredMin(int requiredMin) {
		this.requiredMin = requiredMin;
	}

	public int getRequiredMax() {
		return requiredMax;
	}

	public void setRequiredMax(int requiredMax) {
		this.requiredMax = requiredMax;
	}

}
